package meesterbrein;

import java.awt.Color;
import javax.swing.JButton;

/**
 *
 * @author Laurens van Dijk, s3012557 en Gerdriaan Mulder, s3048764
 */
public class Model {

    private boolean solutionSet = false;
    private Kleur[] oplossing = new Kleur[View.NUMPIECES];
    private Kleur[] lastCombination = new Kleur[View.NUMPIECES];

    /**
     * de kleuren in het spel.
     */
    public enum Kleur {

        Rood {
            Kleur volgende() { return Blauw; }
            Color getColor() { return Color.RED; }
        },
        Blauw {
            Kleur volgende() { return Oranje; }
            Color getColor() { return Color.BLUE; }
        },
        Oranje {
            Kleur volgende() { return Groen; }
            Color getColor() { return Color.ORANGE; }
        },
        Groen {
            Kleur volgende() { return Geel; }
            Color getColor() { return Color.GREEN; }
        },
        Geel {
            Kleur volgende() { return Magenta; }
            Color getColor() { return Color.YELLOW; }
        },
        Magenta {
            Kleur volgende() { return Rood; }
            Color getColor() { return Color.MAGENTA; }
        },
        Grijs {
            Kleur volgende() { return Grijs; }
            Color getColor() { return Color.GRAY; }
        };

        abstract Kleur volgende();
        abstract Color getColor();

        /**
         * geeft de bijhorende enum Kleur.
         * @param k - de kleur om om te zetten.
         * @return
         */
        public static Kleur fromColor(Color k) {
            if (k == Color.RED) { return Rood; }
            else if (k == Color.BLUE) { return Blauw; }
            else if (k == Color.ORANGE) { return Oranje; }
            else if (k == Color.GREEN) { return Groen; }
            else if (k == Color.YELLOW) { return Geel; }
            else if (k == Color.MAGENTA) { return Magenta; }
            return Grijs;
        }

        /**
         * Functie die een integer koppelt aan een kleur, dit is handiger programmeren qua logica.
         * @param i - de integer.
         * @return
         */
        public static Kleur numberedColour(int i) 
        {
            switch(i) {
                case 1: return Rood;
                case 2: return Blauw;
                case 3: return Oranje;
                case 4: return Groen;
                case 5: return Geel;
                case 6: return Magenta;
                default: return Grijs; //let op: dit mag eigenlijk niet gebeuren!
                
            }
        }

        ;
    }

    /**
     * Enum voor de pinnen waarmee hints worden gegeven.
     */
    public enum Pin {
        Goed {
            Pin volgende() { return Half; }
            Color getColor() { return Color.RED; }
        },
        Half {
            Pin volgende() { return Niks; }
            Color getColor() { return Color.WHITE; }
        },
        Niks {
            Pin volgende() { return Goed; }
            Color getColor() { return Color.BLACK; }
        };
        abstract Pin volgende();
        abstract Color getColor();

        /**
         * niet echt bijzonder, geeft de kleur van de huidige pin terug.
         * @param k 
         * @return
         */
        public static Pin fromColor(Color k) {
            if (k == Color.RED) { return Goed; }
            else if (k == Color.WHITE) { return Half; }
            else if (k == Color.BLACK) { return Niks; }
            return Niks;
        }
    }

    /**
     * indien de gegeven combinatie een geldige is, deze in de rij met al geprobeerde combinaties laden.
     * @param guessbtn - de te testen combinatie.
     * @param testedcombinations - de 2d-array met al geprobeerde combinaties.
     * @return
     */
    public boolean combinatieNaarOverzicht(Kleur[] guessbtn, JButton[][] testedcombinations) {
        boolean valideCombinatie = true;
        int row = Controller.aantalCombinaties;
        for (int k = 0; k < View.NUMPIECES; k++) {
            if (guessbtn[k].getColor() == Color.GRAY) {
                valideCombinatie = false;
            }
        }
        if (!valideCombinatie) {
            // niks doen? error weergeven? - G
            System.out.println("INFO: I_NOVALIDCOMBINATION, een van de vakjes is nog grijs :-( ");
        } else {
            if (row < View.NUMROWS) {
                for (int k = 0; k < View.NUMPIECES; k++) {
                    testedcombinations[row][k].setBackground(guessbtn[k].getColor());
                }
                Controller.aantalCombinaties++;
                return true;
            } else {
                // berichtje geven dat maximumaantal zetten is bereikt?
                System.out.println("ERROR: E_MAXNUMSTEPS, spel ist vorbei!");
            }
        }
        return false;
    }

    /**
     * Ditto als voorgaande functie, maar dan indien de mens codemaker is, en dus een solution moet bedenken.
     * @param codebtn - de JButtons waar de code mee kan worden ingevoerd.
     * @param solution - de JButtons die de oplossing weergeven.
     */
    public void combinatieNaarSolution(Kleur[] codebtn, JButton[] solution) {
        boolean valideCombinatie = true;
        for (int k = 0; k < View.NUMPIECES; k++) {
            if (codebtn[k].getColor() == Color.GRAY) {
                valideCombinatie = false;
            }
        }
        if (!valideCombinatie) {
            // niks doen? error weergeven? - G
            System.out.println("INFO: I_NOVALIDCOMBINATION, een van de vakjes is nog grijs :-( ");
        } else {
            if (!solutionSet) {
                for (int k = 0; k < View.NUMPIECES; k++) {
                    solution[k].setBackground(codebtn[k].getColor());
                }
                solutionSet = true;
            } else {
                // berichtje geven dat er al een oplossing is ingesteld.
                System.out.println("ERROR: E_SOLUTIONSET, oplossing is al ingesteld!");
            }
        }
    }

    /**
     * wederom idem ditto, maar dan voor de hints-pinnen.
     * @param pinnen - de pinnen die op dit moment door de gebruiker danwel ai worden ingesteld.
     * @param pinbtns - de array waarmee pinnen die al zijn ingesteld worden weergegeven.
     */
    public void hintsNaarPinnetjes(Pin[] pinnen, JButton[][] pinbtns) {
        int row = Controller.aantalCombinaties-1;
        if (row < View.NUMROWS) {
                for (int k = 0; k < View.NUMPIECES; k++) {
                    pinbtns[row][k].setBackground(pinnen[k].getColor());
                }
                System.out.println("DEBUG hintsNaarPinnetjes: used row "+row);
        } else {
            // berichtje dat het maximumaantal hints is bereikt
            System.out.println("ERROR: E_MAXNUMSTEPS, het is voorbij!");
        }
    }

    /**
     * genereert een Kleur-array vanuit een JButton array
     * @param j array van JButtons
     * @return array van type Kleur
     */
    public Kleur[] getKleurFromJButtons(JButton[] j) {
        int numJButton = j.length;
        Kleur k[] = new Kleur[numJButton];
        for (int i = 0; i < numJButton; i++) {
            k[i] = Kleur.fromColor(j[i].getBackground());
        }
        return k;
    }


    /**
     * genereert een pin-array vanuit een JButton array.
     * @param j - de buttons waarmee de pinnen worden ingesteld.
     * @return array van type Pin
     */
    public Pin[] getPinsFromJButtons(JButton[] j) {
        int numJButton = j.length;
        Pin k[] = new Pin[numJButton];
        for (int i = 0; i < numJButton; i++) {
            k[i] = Pin.fromColor(j[i].getBackground());
        }
        return k;
    }

    /**
     * simpele functie, stelt de oplossing in.
     * @param k - een array van kleuren.
     */
    public void setOplossing(Kleur[] k) {
        if (k.length <= View.NUMPIECES) {
            for (int i=0;i < k.length; i++) {
                oplossing[i] = k[i];
            }
        }
    }

    /**
     * geeft de oplossing terug.
     * @return de oplossing
     */
    public Kleur[] getOplossing() {
        return oplossing;
    }

    /**
     * geeft aan of de te kraken code al is ingesteld
     * @return is de te kraken code ingesteld?
     */
    public boolean getSolutionState() {
        return solutionSet;
    }
    /**
     * geeft de laatst gekozen combinatie terug.
     * @return de laatst gekozen combinatie
     */
    public Kleur[] getLastCombination() {
        return lastCombination;
    }

    /**
     * idem als voorgaande functie.
     * @param c - een array van kleuren.
     */
    public void setLastCombination(Kleur[] c) {
        if (c.length <= View.NUMPIECES) {
            lastCombination = c;
        }
    }
}
